home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 24 / CU Amiga Magazine's Super CD-ROM 24 (1998)(EMAP Images)(GB)(Track 1 of 2)[!][issue 1998-07].iso / CUCD / Programming / SWI / source / src / chpl.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-02-19  |  7.3 KB  |  414 lines

  1. /*  $Id: chpl.c,v 1.4 1996/02/19 15:55:53 jan Exp $
  2.  
  3.     Designed and implemented by Jan Wielemaker
  4.     E-mail: jan@swi.psy.uva.nl
  5.  
  6.     Copyright (C) 1995 University of Amsterdam. All rights reserved.
  7. */
  8.  
  9. #include "pl-incl.h"
  10. #include <stdio.h>
  11. #include <string.h>
  12. #include <stdarg.h>
  13. #ifdef HAVE_UNISTD_H
  14. #include <unistd.h>
  15. #endif
  16. #ifdef HAVE_SYS_FILE_H
  17. #include <sys/file.h>
  18. #endif
  19. #include <stdlib.h>
  20. #include <sys/stat.h>
  21. #include <errno.h>
  22.  
  23. #define closeFiles chplCloseFiles
  24. #define warning chplWarning
  25.  
  26. #ifndef EOS
  27. #define EOS '\0'
  28. #endif
  29. #define MAXLINE 1024
  30. #ifndef MAXPATHLEN
  31. #define MAXPATHLEN 1024
  32. #endif
  33.  
  34. #define ENDHEADER "# End Header\n"
  35.  
  36. #define VERBOSE(g) if ( verbose ) { g; }
  37.  
  38. static char *program;
  39. static char *state      = NULL;        /* program to work on */
  40. static char *emulator   = NULL;        /* -e */
  41. static char *outfile    = NULL;        /* -o */
  42. static char *headerfile = NULL;        /* -h */
  43. static int  verbose     = 0;        /* -v */
  44. static int  extract     = 0;        /* -x */
  45.  
  46. void
  47. warning(char *fm, ...)
  48. { va_list args;
  49.  
  50.   va_start(args, fm);
  51.   fprintf(stderr, "%s: ", program);
  52.   vfprintf(stderr, fm, args);
  53.   fprintf(stderr, "\n");
  54.   va_end(args);
  55. }
  56.  
  57.  
  58. void
  59. usage()
  60. { fprintf(stderr, "usage: %s -e emulator [-o outfile] state\n", program);
  61.   fprintf(stderr, "   or: %s -x [-o outfile] state\n", program);
  62.   fprintf(stderr, "   or: %s -h header [-o outfile] state\n", program);
  63.  
  64.   exit(1);
  65. }
  66.  
  67.  
  68. char *
  69. OsError(void)
  70. {
  71. #ifdef HAVE_STRERROR
  72. #ifdef __WIN32__
  73.   return strerror(_xos_errno());
  74. #else
  75.   return strerror(errno);
  76. #endif
  77. #else /*HAVE_STRERROR*/
  78.   static char errmsg[64];
  79.  
  80. #if unix
  81.   extern int sys_nerr;
  82. #if !EMX
  83.   extern char *sys_errlist[];
  84. #endif
  85.   extern int errno;
  86.  
  87.   if ( errno < sys_nerr )
  88.     return sys_errlist[errno];
  89. #endif
  90.  
  91.   sprintf(errmsg, "Unknown Error (%d)", errno);
  92.   return errmsg;
  93. #endif /*HAVE_STRERROR*/
  94. }
  95.  
  96.  
  97. int
  98. replacevar(char *line, char *var, char *value)
  99. { char *s;
  100.   int varl = strlen(var);
  101.  
  102.   for(s=line; *s; s++)
  103.   { if ( *s == '$' && s[1] == '{' )
  104.     { s += 2;
  105.       if ( strncmp(s, var, varl) == 0 && s[varl] == '-' )
  106.       { char *e;
  107.  
  108.     s += varl+1;
  109.     if ( (e = strchr(s, '}')) )
  110.     { char buf[MAXLINE];
  111.  
  112.       strcpy(buf, e);
  113.       strcpy(s, value);
  114.       strcat(s, buf);
  115.       return 1;
  116.     }
  117.       }
  118.     }
  119.   }
  120.  
  121.   return 0;
  122. }
  123.  
  124.  
  125. static int
  126. cpmode(char *from, char *to)
  127. { struct stat buf;
  128.  
  129.   if ( stat(from, &buf) == 0 )
  130.   { return chmod(to, buf.st_mode);
  131.   }
  132.  
  133.   return -1;
  134. }
  135.  
  136.  
  137. static int
  138. openFiles(char *qlf, char *outfile, char *tmpqlf, FILE **in, FILE **out)
  139. { strcpy(tmpqlf, ".");
  140.   strcat(tmpqlf, outfile);
  141.  
  142.   if ( (*in = fopen(qlf, "rb")) == NULL )
  143.   { warning("cannot open %s: %s", qlf, OsError());
  144.     return 1;
  145.   }
  146.   if ( (*out = fopen(tmpqlf, "wb")) == NULL )
  147.   { warning("cannot open %s: %s", tmpqlf, OsError());
  148.     return 1;
  149.   }
  150.  
  151.   return 0;
  152. }
  153.  
  154. static int
  155. closeFiles(char *qlf, char *outfile, char *tmpqlf, FILE *in, FILE *out)
  156. { if ( ferror(in) )
  157.   { warning("Error reading %s: %s\n", qlf, OsError());
  158.     return 1;
  159.   }
  160.   if ( ferror(out) )
  161.   { warning("Error writing %s: %s\n", tmpqlf, OsError());
  162.     return 1;
  163.   }
  164.  
  165.   fclose(in);
  166.   fclose(out);
  167.  
  168.   if ( cpmode(qlf, tmpqlf) != 0 )
  169.     warning("failed to copy mode from %s to %s: %s", qlf, tmpqlf, OsError());
  170.  
  171.   if ( rename(tmpqlf, outfile) )
  172.   { warning("failed to rename %s into %s: %s", tmpqlf, qlf, OsError());
  173.     return 1;
  174.   }
  175.  
  176.   return 0;
  177. }
  178.  
  179.  
  180. static int
  181. copyFd(FILE *in, FILE *out, char *infile, char *outfile)
  182. { char line[MAXLINE];
  183.  
  184.   for(;;)
  185.   { char *s;
  186.     int n;
  187.  
  188.     for(s=line, n=0; n<sizeof(line); n++)
  189.     { int c = fgetc(in);
  190.  
  191.       if ( c == EOF )
  192.       { char *q = line;
  193.  
  194.     for( ; q<s; q++)
  195.     { if ( fputc(*q, out) < 0 )
  196.       { warning("write failed on %s: %s", outfile, OsError());
  197.         return 1;
  198.       }
  199.     }
  200.     return 0;
  201.       } else
  202.     *s++ = c;
  203.     }
  204.     for(s=line, n=0; n<sizeof(line); n++)
  205.     { if ( fputc(*s++, out) < 0 )
  206.       { warning("write failed on %s: %s", outfile, OsError());
  207.     return 1;
  208.       }
  209.     }
  210.   }
  211. }
  212.  
  213.  
  214. int
  215. changeEmulator(char *qlf, char *emulator, char *outfile)
  216. { char tmpqlf[MAXPATHLEN];
  217.   char line[MAXLINE];
  218.   FILE *in, *out;
  219.   int n;
  220.  
  221.   if ( openFiles(qlf, outfile, tmpqlf, &in, &out) )
  222.     return 1;
  223.  
  224.   for(n=0; n<100; n++)
  225.   { if ( !fgets(line, sizeof(line), in) )
  226.     { warning("%s: not a SWI-Prolog saved state", qlf);
  227.       return 1;
  228.     }
  229.     if ( replacevar(line, "SWIPL", emulator) )
  230.     { fputs(line, out);
  231.       goto copy;
  232.     }
  233.     fputs(line, out);
  234.   }
  235.   warning("%s: not a SWI-Prolog saved state", qlf);
  236.   return 1;
  237.  
  238. copy:
  239.   if ( copyFd(in, out, qlf, tmpqlf) )
  240.     return 1;
  241.  
  242.   return closeFiles(qlf, outfile, tmpqlf, in, out);
  243. }
  244.  
  245.  
  246. int
  247. extractHeader(char *qlf, char *outfile)
  248. { FILE *in, *out;
  249.   char line[MAXLINE];
  250.  
  251.   if ( (in = fopen(qlf, "rb")) == NULL )
  252.   { warning("cannot open %s: %s", qlf, OsError());
  253.     return 1;
  254.   }
  255.   if ( !outfile )
  256.     out = stdout;
  257.   else
  258.   { if ( (out = fopen(outfile, "wb")) == NULL )
  259.     { warning("cannot open %s: %s", outfile, OsError());
  260.       return 1;
  261.     }
  262.   }
  263.  
  264.   for(;;)
  265.   { if ( !fgets(line, sizeof(line), in) )
  266.     { warning("%s: Could not find %s", qlf, ENDHEADER);
  267.       return 1;
  268.     }
  269.  
  270.     if ( strcmp(line, ENDHEADER) == 0 )
  271.       break;
  272.  
  273.     if ( fputs(line, out) < 0 )
  274.     { warning("write failed: %s\n", OsError());
  275.       return 1;
  276.     }
  277.   }
  278.  
  279.   fflush(out);
  280.   if ( outfile )
  281.     fclose(out);
  282.   fclose(in);
  283.  
  284.   return 0;
  285. }
  286.  
  287.  
  288. static int
  289. skipHeader(FILE *in, char *file)
  290. { char line[MAXLINE];
  291.  
  292.   for(;;)
  293.   { if ( !fgets(line, sizeof(line), in) )
  294.     { warning("%s: Could not find %s", file, ENDHEADER);
  295.       return 1;
  296.     }
  297.     if ( strcmp(line, ENDHEADER) == 0 )
  298.       break;
  299.   }
  300.  
  301.   return 0;
  302. }
  303.  
  304.  
  305. int
  306. replaceHeader(char *qlf, char *headerfile, char *outfile)
  307. { char tmpqlf[MAXPATHLEN];
  308.   FILE *in, *out, *hf;
  309.  
  310.   if ( openFiles(qlf, outfile, tmpqlf, &in, &out) )
  311.     return 1;
  312.  
  313.   if ( strcmp(headerfile, "-") == 0 )
  314.     hf = stdin;
  315.   else if ( (hf = fopen(headerfile, "r")) == NULL )
  316.   { warning("Failed to open %s: %s", headerfile, OsError());
  317.     return 1;
  318.   }
  319.   
  320.   if ( copyFd(hf, out, headerfile, tmpqlf) )
  321.     return 1;
  322.   fprintf(out, "%s", ENDHEADER);
  323.   if ( skipHeader(in, qlf) ||
  324.        copyFd(in, out, qlf, tmpqlf) )
  325.     return 1;
  326.  
  327.   return closeFiles(qlf, outfile, tmpqlf, in, out);
  328. }
  329.  
  330.  
  331. char *
  332. baseName(char *path)
  333. { char *b;
  334.  
  335.   for(b=path; *path; path++)
  336.   { if ( *path == '/' )
  337.       b = &path[1];
  338.   }
  339.  
  340.   return b;
  341. }
  342.  
  343.  
  344. int
  345. main(int argc, char **argv)
  346. { program = baseName(argv[0]);
  347.  
  348.   argc--; argv++;
  349.   while(argc > 0 && argv[0][0] == '-')
  350.   { char *opts = &argv[0][1];
  351.  
  352.     argc--; argv++;
  353.     for(; *opts; opts++)
  354.     { switch(*opts)
  355.       { case 'e':
  356.       if ( argc <= 0 )
  357.         usage();
  358.       emulator = argv[0];
  359.       argc--; argv++;
  360.       continue;
  361.     case 'o':
  362.       if ( argc <= 0 )
  363.         usage();
  364.       outfile = argv[0];
  365.       argc--; argv++;
  366.       continue;
  367.     case 'x':
  368.       extract++;
  369.       continue;
  370.     case 'h':
  371.       if ( argc <= 0 )
  372.         usage();
  373.       headerfile = argv[0];
  374.       argc--; argv++;
  375.     case 'v':
  376.       verbose++;
  377.       continue;
  378.       }
  379.     }
  380.   }
  381.  
  382.   if ( argc != 1 )
  383.     usage();
  384.   state = argv[0];
  385.  
  386.   if ( extract )
  387.   { exit(extractHeader(state, outfile));
  388.   }
  389.  
  390.   if ( !outfile )
  391.     outfile = state;
  392.  
  393.   if ( headerfile )
  394.   { exit(replaceHeader(state, headerfile, outfile));
  395.   }
  396.  
  397.   if ( emulator )
  398.   { if ( emulator[0] != '/' )
  399.     { warning("Path to emulator must be absolute");
  400.       exit(1);
  401.     }
  402.     if ( access(emulator, X_OK) != 0 )
  403.       warning("%s: emulator is not executable: %s\n", emulator, OsError());
  404.  
  405.  
  406.     exit(changeEmulator(state, emulator, outfile));
  407.   }
  408.  
  409.   usage();
  410.   return 1;
  411. }
  412.  
  413.  
  414.